}
gboolean
-_ostree_repo_open_untrusted_content_bare (OstreeRepo *self,
- const char *expected_checksum,
- guint64 content_len,
- OstreeRepoContentBareCommit *out_state,
- GOutputStream **out_stream,
- gboolean *out_have_object,
- GCancellable *cancellable,
- GError **error)
-{
- /* The trusted codepath is fine here */
- return _ostree_repo_open_trusted_content_bare (self,
- expected_checksum,
- content_len,
- out_state,
- out_stream,
- out_have_object,
- cancellable,
- error);
-}
-
-gboolean
-_ostree_repo_commit_untrusted_content_bare (OstreeRepo *self,
- const char *expected_checksum,
- OstreeRepoContentBareCommit *state,
- guint32 uid,
- guint32 gid,
- guint32 mode,
- GVariant *xattrs,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
-
- if (state->fd != -1)
- {
- GMappedFile *mapped;
- g_autoptr(GBytes) bytes = NULL;
- g_autoptr(GInputStream) raw_in = NULL;
- g_autoptr(GInputStream) in = NULL;
- g_autoptr(GFileInfo) file_info = NULL;
- g_autofree guchar *actual_csum = NULL;
- g_autofree char *actual_checksum = NULL;
- int fd;
-
- fd = openat (self->tmp_dir_fd, state->temp_filename, O_RDONLY);
- if (fd == -1)
- {
- glnx_set_error_from_errno (error);
- goto out;
- }
-
- mapped = g_mapped_file_new_from_fd (fd, FALSE, error);
-
- close (fd);
- if (mapped == NULL)
- goto out;
-
- bytes = g_mapped_file_get_bytes (mapped);
- g_mapped_file_unref (mapped);
-
- raw_in = g_memory_input_stream_new_from_bytes (bytes);
-
- file_info = _ostree_header_gfile_info_new (mode, uid, gid);
-
- if (!ostree_raw_file_to_content_stream (raw_in, file_info, xattrs, &in, NULL, cancellable, error))
- goto out;
-
- if (!ot_gio_checksum_stream (in, &actual_csum, cancellable, error))
- goto out;
-
- actual_checksum = ostree_checksum_from_bytes (actual_csum);
-
- if (strcmp (actual_checksum, expected_checksum) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted object %s (actual checksum is %s)",
- expected_checksum, actual_checksum);
- goto out;
- }
-
- if (!commit_loose_object_trusted (self, expected_checksum, OSTREE_OBJECT_TYPE_FILE,
- state->temp_filename,
- FALSE, uid, gid, mode,
- xattrs, state->fd,
- cancellable, error))
- goto out;
- }
-
- ret = TRUE;
- out:
- g_free (state->temp_filename);
- return ret;
-}
-
-gboolean
-_ostree_repo_open_trusted_content_bare (OstreeRepo *self,
- const char *checksum,
- guint64 content_len,
- OstreeRepoContentBareCommit *out_state,
- GOutputStream **out_stream,
- gboolean *out_have_object,
- GCancellable *cancellable,
- GError **error)
+_ostree_repo_open_content_bare (OstreeRepo *self,
+ const char *checksum,
+ guint64 content_len,
+ OstreeRepoContentBareCommit *out_state,
+ GOutputStream **out_stream,
+ gboolean *out_have_object,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
g_autofree char *temp_filename = NULL;
OstreeRepoContentBareCommit barecommitstate;
guint64 content_size;
GOutputStream *content_out;
+ GChecksum *content_checksum;
char checksum[OSTREE_SHA256_STRING_LEN+1];
char *read_source_object;
int read_source_fd;
return TRUE;
}
+static gboolean
+content_out_write (OstreeRepo *repo,
+ StaticDeltaExecutionState *state,
+ const guint8* buf,
+ gsize len,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gsize bytes_written;
+
+ if (state->content_checksum)
+ g_checksum_update (state->content_checksum, buf, len);
+
+ /* Ignore bytes_written since we discard partial content */
+ if (!g_output_stream_write_all (state->content_out,
+ buf, len,
+ &bytes_written,
+ cancellable, error))
+ return FALSE;
+
+ return TRUE;
+}
+
static gboolean
do_content_open_generic (OstreeRepo *repo,
StaticDeltaExecutionState *state,
g_autofree guchar *buf = NULL;
struct bspatch_stream stream;
struct bzpatch_opaque_s opaque;
- gsize bytes_written;
if (!read_varuint64 (state, &offset, error))
goto out;
&stream) < 0)
goto out;
- if (!g_output_stream_write_all (state->content_out,
- buf,
- state->content_size,
- &bytes_written,
- cancellable, error))
+ if (!content_out_write (repo, state, buf, state->content_size,
+ cancellable, error))
goto out;
-
- g_assert (bytes_written == state->content_size);
}
ret = TRUE;
return ret;
}
+/* When processing untrusted static deltas, we need to checksum the
+ * file content, which includes a header. Compare with what
+ * ostree_checksum_file_from_input() is doing too.
+ */
+static gboolean
+handle_untrusted_content_checksum (OstreeRepo *repo,
+ StaticDeltaExecutionState *state,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(GVariant) header = NULL;
+ g_autoptr(GFileInfo) finfo = NULL;
+ gsize bytes_written;
+
+ if (state->trusted)
+ return TRUE;
+
+ finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid);
+ header = _ostree_file_header_new (finfo, state->xattrs);
+
+ state->content_checksum = g_checksum_new (G_CHECKSUM_SHA256);
+
+ if (!_ostree_write_variant_with_size (NULL, header, 0, &bytes_written, state->content_checksum,
+ cancellable, error))
+ return FALSE;
+
+ return TRUE;
+}
+
static gboolean
dispatch_open_splice_and_close (OstreeRepo *repo,
StaticDeltaExecutionState *state,
{
guint64 content_offset;
guint64 objlen;
- gsize bytes_written;
g_autoptr(GInputStream) object_input = NULL;
g_autoptr(GInputStream) memin = NULL;
(repo->mode == OSTREE_REPO_MODE_BARE ||
repo->mode == OSTREE_REPO_MODE_BARE_USER))
{
- if (state->trusted)
- {
- if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
- state->content_size,
- &state->barecommitstate,
- &state->content_out,
- &state->have_obj,
- cancellable, error))
- goto out;
- }
- else
- {
- if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum,
- state->content_size,
- &state->barecommitstate,
- &state->content_out,
- &state->have_obj,
- cancellable, error))
- goto out;
- }
+ if (!_ostree_repo_open_content_bare (repo, state->checksum,
+ state->content_size,
+ &state->barecommitstate,
+ &state->content_out,
+ &state->have_obj,
+ cancellable, error))
+ goto out;
if (!state->have_obj)
{
- if (!g_output_stream_write_all (state->content_out,
- state->payload_data + content_offset,
- state->content_size,
- &bytes_written,
- cancellable, error))
+ if (!handle_untrusted_content_checksum (repo, state, cancellable, error))
+ goto out;
+
+ if (!content_out_write (repo, state,
+ state->payload_data + content_offset,
+ state->content_size,
+ cancellable, error))
goto out;
}
}
ret = TRUE;
goto out;
}
+
+ if (!_ostree_repo_open_content_bare (repo, state->checksum,
+ state->content_size,
+ &state->barecommitstate,
+ &state->content_out,
+ &state->have_obj,
+ cancellable, error))
+ goto out;
- if (state->trusted)
- {
- if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
- state->content_size,
- &state->barecommitstate,
- &state->content_out,
- &state->have_obj,
- cancellable, error))
- goto out;
- }
- else
- {
- if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum,
- state->content_size,
- &state->barecommitstate,
- &state->content_out,
- &state->have_obj,
- cancellable, error))
- goto out;
- }
+ if (!handle_untrusted_content_checksum (repo, state, cancellable, error))
+ goto out;
ret = TRUE;
out:
gboolean ret = FALSE;
guint64 content_size;
guint64 content_offset;
- gsize bytes_written;
if (!read_varuint64 (state, &content_size, error))
goto out;
goto out;
}
- if (!g_output_stream_write_all (state->content_out,
- buf,
- bytes_read,
- &bytes_written,
- cancellable, error))
+ if (!content_out_write (repo, state, (guint8*)buf, bytes_read,
+ cancellable, error))
goto out;
content_size -= bytes_read;
if (!validate_ofs (state, content_offset, content_size, error))
goto out;
- if (!g_output_stream_write_all (state->content_out,
- state->payload_data + content_offset,
- content_size,
- &bytes_written,
- cancellable, error))
+ if (!content_out_write (repo, state, state->payload_data + content_offset, content_size,
+ cancellable, error))
goto out;
}
}
if (!g_output_stream_flush (state->content_out, cancellable, error))
goto out;
- if (state->trusted)
+ if (state->content_checksum)
{
- if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate,
- state->uid, state->gid, state->mode,
- state->xattrs,
- cancellable, error))
- goto out;
- }
- else
- {
- if (!_ostree_repo_commit_untrusted_content_bare (repo, state->checksum, &state->barecommitstate,
- state->uid, state->gid, state->mode,
- state->xattrs,
- cancellable, error))
- goto out;
+ const char *actual_checksum = g_checksum_get_string (state->content_checksum);
+
+ g_assert (!state->trusted);
+
+ if (strcmp (actual_checksum, state->checksum) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Corrupted object %s (actual checksum is %s)",
+ state->checksum, actual_checksum);
+ goto out;
+ }
}
+
+ if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate,
+ state->uid, state->gid, state->mode,
+ state->xattrs,
+ cancellable, error))
+ goto out;
}
if (!dispatch_unset_read_source (repo, state, cancellable, error))